package com.share.base.advice;

import com.share.base.constant.Result;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.SQLException;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.stream.Collectors;


@RestControllerAdvice
public class ErrorControllerAdvice {

    // 处理参数绑定异常
    @ExceptionHandler(value = BindException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Result handleBindException(BindException exception, HttpServletResponse response) {
        response.setStatus(HttpStatus.BAD_REQUEST.value());
        List<FieldError> fieldErrors = exception.getFieldErrors();
        String errorMessage = fieldErrors.stream()
                .map(FieldError::getDefaultMessage)
                .collect(Collectors.joining(", "));
        Result result = Result.fail(400, "参数绑定错误: " + errorMessage, null);
        return result;
    }

    // 处理参数验证异常
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST) // 指定HTTP状态码
    public Result handleMethodArgumentNotValidException(MethodArgumentNotValidException ex) {
        List<FieldError> fieldErrors = ex.getBindingResult().getFieldErrors();

        // 将错误信息构建成列表，以便客户端能更好地解析
        List<String> errorMessages = fieldErrors.stream()
                .map(FieldError::getDefaultMessage)
                .collect(Collectors.toList());

        // 构建返回结果，不包含HTTP状态码，因为它已经由@ResponseStatus处理
        return Result.fail(400,"参数验证错误"+ errorMessages, null);
    }


    // 请求格式不支持异常
    @ExceptionHandler(value = HttpMediaTypeNotSupportedException.class)
    @ResponseStatus(HttpStatus.UNSUPPORTED_MEDIA_TYPE)
    public Result handleHttpMediaTypeNotSupportedException(HttpMediaTypeNotSupportedException exception, HttpServletResponse response) {
        response.setStatus(HttpStatus.BAD_REQUEST.value());
        Result result = Result.fail(415, "请求数据格式错误: " + exception.getMessage(), null);
        return result;
    }

    // 处理 SQL 异常
    @ExceptionHandler(value = SQLException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public Result handleSQLException(SQLException exception, HttpServletResponse response) {
        response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
        Result result = Result.fail(500, "SQL 错误: " + exception.getMessage(), null);
        return result;
    }

    // 处理文件未找到异常
    @ExceptionHandler(value = FileNotFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public Result handleFileNotFoundException(FileNotFoundException exception, HttpServletResponse response) {
        response.setStatus(HttpStatus.NOT_FOUND.value());
        Result result = Result.fail(404, "文件未找到: " + exception.getMessage(), null);
        return result;
    }


    // 处理所有未捕获的异常
    @ExceptionHandler(value = Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public Result handleException(Exception exception, HttpServletResponse response) {
        response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
        Result result = Result.fail(500, "服务器内部错误: " + exception.getMessage(), null);
        return result;
    }

    // ServletException异常处理
    @ExceptionHandler(value = ServletException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public Result handleServletException(ServletException exception, HttpServletResponse response) {
        response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
        Result result = Result.fail(500, "Servlet异常: " + exception.getMessage(), null);
        return result;
    }

    //IOException异常处理
    @ExceptionHandler(value = IOException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public Result handleIOException(IOException exception, HttpServletResponse response) {
        response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
        Result result = Result.fail(500, "IO异常: " + exception.getMessage(), null);
        return result;
    }

    // 其他异常处理


    /**
     * 处理空指针异常
     */

    @ExceptionHandler(value = NullPointerException.class)
    public Result handleNullPointerException(NullPointerException exception, HttpServletResponse response) {
        response.setStatus(HttpStatus.BAD_REQUEST.value());
        return Result.fail(400, "请求参数不能为空" + exception.getMessage(), null);
    }

    /**
     * 处理非法参数异常
     */
    @ExceptionHandler(value = IllegalArgumentException.class)
    public Result handleIllegalArgumentException(IllegalArgumentException exception, HttpServletResponse response) {
        response.setStatus(HttpStatus.BAD_REQUEST.value());
        return Result.fail(400, "非法参数: " + exception.getMessage(), null);
    }

    /**
     * 处理查询不到数据异常
     */
    @ExceptionHandler(value = NoSuchElementException.class)
    public Result handleNoSuchElementException(NoSuchElementException exception, HttpServletResponse response) {
        response.setStatus(HttpStatus.NOT_FOUND.value());
        return Result.fail(404, "请求的数据未找到: " + exception.getMessage(), null);
    }

    /**
     * 处理格式化异常
     */

    @ExceptionHandler(value = NumberFormatException.class)
    public Result handleNumberFormatException(NumberFormatException exception, HttpServletResponse response) {
        response.setStatus(HttpStatus.BAD_REQUEST.value());
        return Result.fail(400, "数字格式错误: " + exception.getMessage(), null);
    }

    /**
     * 在SQL语句中违反了唯一约定
     */

    @ExceptionHandler(value = DataIntegrityViolationException.class)
    public Result handleDataIntegrityViolationException(DataIntegrityViolationException exception, HttpServletResponse response) {
        response.setStatus(HttpStatus.CONFLICT.value());
        return Result.fail(409, "数据冲突: " + exception.getMessage(), null);
    }

}
